const axios = require('axios');
module.exports = {
    // 插件名字
    name: "esp-ai-plugin-LLM-handlejson",
    // 插件类型 LLM | TTS | IAT
    type: "LLM", 
    main,
}


/**
 * 大语言模型插件
 * @param {String}      device_id           设备id 
 * @param {Number}      devLog              日志输出等级，为0时不应该输出任何日志   
 * @param {Object}      llm_config          用户配置的 apikey 等信息   
 * @param {String}      iat_server          用户配置的 iat 服务 
 * @param {String}      llm_server          用户配置的 llm 服务 
 * @param {String}      tts_server          用户配置的 tts 服务 
 * @param {String}      text                对话文本
 * @param {Function}    connectServerBeforeCb 连接 LLM 服务逻辑开始前需要调用这个方法告诉框架：eg: connectServerBeforeCb()
 * @param {Function}    connectServerCb     连接 LLM 服务后需要调用这个方法告诉框架：eg: connectServerCb(true)
 * @param {Function}    cb                  LLM 服务返回音频数据时调用，eg: cb({  count_text, text, texts })
 * @param {Function}    llmServerErrorCb    与 LLM 服务之间发生错误时调用，并且传入错误说明，eg: llmServerErrorCb("意外错误")
 * @param {Function}    llm_params_set      用户配置的设置 LLM 参数的函数
 * @param {Function}    logWSServer         将 ws 服务回传给框架，如果不是ws服务可以这么写: logWSServer({ close: ()=> {  中断逻辑... } })
 * @param {{role, content}[]}  llm_init_messages   用户配置的初始化时的对话数据
 * @param {{role, content}[]}  llm_historys llm 历史对话数据
 * @param {Function}    log                 为保证日志输出的一致性，请使用 log 对象进行日志输出，eg: log.error("错误信息")、log.info("普通信息")、log.llm_info("llm 专属信息")
 *  
*/
async function main({ devLog, is_pre_connect, llm_config, text, llmServerErrorCb, llm_init_messages = [], llm_historys = [], cb, llm_params_set, logWSServer, connectServerBeforeCb, connectServerCb, log }) {
    try {
        const { url = 'https://api.espai2.fun/ai_api/llm', api_key, model = "qwen2.5:32b", ...other_config } = llm_config;
        if (!api_key) return log.error(`请配给 LLM 配置 api_key 参数。`)

            
        // 预先连接函数
        async function preConnect() {
            try { 
                await axios.post(url, {
                    messages: [{ "role": "user", "content": "" }],
                    "model": model, "api_key": api_key
                }, { headers: { 'Content-Type': 'application/json' } }) 
            } catch (error) {
                log.error('预先连接失败:', error);
            }
        }
        if (is_pre_connect) {
            preConnect()
            return;
        }


        // 如果关闭后 message 还没有被关闭，需要定义一个标志控制
        let shouldClose = false;
        // 这个对象是固定写法，每个 TTS 都必须按这个结构定义
        const texts = {
            all_text: "",
            count_text:"",
            index: 0,
        }

        const data = {
            ...other_config,
            "message": [
                ...llm_init_messages,
                ...llm_historys,
                {
                    "role": "user",
                    "content": text
                }
            ],
            "model": model,
            "api_key": api_key
        };

        logWSServer({
            close: () => {
                shouldClose = true;
            }
        })
        connectServerBeforeCb();
 
        // 修改为非流式传输
        axios.post(url, llm_params_set ? llm_params_set({ ...data }) : data, {
            headers: { 'Content-Type': 'application/json' }
            // 删除 responseType: 'stream'
        }).then((response) => { 
            connectServerCb(true);
            
            // 获取完整响应
            const responseData = response.data;
            devLog === 2 && log.llm_info('LLM 完整响应：', responseData);
            // console.log("测试：",responseData.response);
            // 检查响应是否成功
            if (responseData?.success === false) {
                console.error(`ESP-AI-LLM 服务错误：${responseData.message}`);
                llmServerErrorCb(`ESP-AI-LLM 服务错误：${responseData.message}`, responseData.code);
                connectServerCb(false);
                return;
            }
            
            // 将响应内容保存到texts对象
            let responseText = typeof responseData === 'string' ? responseData : JSON.stringify(responseData);
            texts["count_text"] = responseText;
            // console.log(typeof responseData,":",JSON.stringify(responseData));
            // 一次性返回完整结果
            cb({ text, is_over: true, texts, chunk_text: responseText, shouldClose });
            
            connectServerCb(false);
            devLog && log.llm_info("LLM 结果： " + texts["count_text"]);
            devLog && log.llm_info('LLM connect close!\n');
            
        }).catch((err) => {
            // 处理错误
            console.error('Request error:', err);
            connectServerCb(false);
            llmServerErrorCb("llm connect err: " + err);
        });


    } catch (err) {
        connectServerCb(false);
        console.log(err);
        log.error("ESP-AI-LLM 插件错误：", err)
    }

}
